package robotics;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.LayoutManager2;
import java.awt.Rectangle;
import java.util.HashMap;

public class AnchorLayout implements LayoutManager2 {

    private int preferredWidth, preferredHeight, minHeight, minWidth;
    private HashMap constraintMap = new HashMap();
    private boolean sizesCalculated = false;
    private Container container;

    public AnchorLayout() {
        super();
    }

    void initialize(Container parent) {
        if (sizesCalculated) {
            return;
        }
        Component[] children = parent.getComponents();
        preferredWidth = 10000;
        preferredHeight = 10000;
        minWidth = 0;
        minHeight = 0;
        Rectangle pb = parent.getBounds();
        for (int i = 0; i < children.length; i++) {
            Component child = children[i];
            if (child != null) {
                Object ld = constraintMap.get(child);
                Rectangle b = child.getBounds();
                Dimension pref = child.getPreferredSize();
                Dimension min = child.getMaximumSize();
                if (pref == null) {
                    pref = child.getSize();
                }
                if (min == null) {
                    min = child.getSize();
                }
                int minX = b.x + b.width;
                int minY = b.y + b.height;
                int maxX = b.x + b.width;
                int maxY = b.y + b.height;
                if (ld instanceof AnchorConstraint) {
                    AnchorConstraint ac = (AnchorConstraint) ld;
                    int acl = ac.left;
                    int acr = ac.right;
                    int aclt = ac.leftType;
                    int acrt = ac.rightType;

                    if (aclt == AnchorConstraint.ANCHOR_REL) {
                        acl = acl * pb.width / 1000;
                    }
                    if (acrt == AnchorConstraint.ANCHOR_REL) {
                        acr = pb.width - acr * pb.width / 1000;
                    }

                    if (aclt != AnchorConstraint.ANCHOR_NONE
                            && acrt != AnchorConstraint.ANCHOR_NONE) {
                        maxX = acl + pref.width + acr;
                    }
                    if (aclt == AnchorConstraint.ANCHOR_NONE) {
                        acl = 0;
                    }
                    if (acrt == AnchorConstraint.ANCHOR_NONE) {
                        acr = 0;
                    }
                    minX = acl + min.width + acr;

                    int act = ac.top;
                    int acb = ac.bottom;
                    int actt = ac.topType;
                    int acbt = ac.bottomType;
                    if (actt == AnchorConstraint.ANCHOR_REL) {
                        act = act * pb.height / 1000;
                    }
                    if (acbt == AnchorConstraint.ANCHOR_REL) {
                        acb = pb.height - acb * pb.height / 1000;
                    }

                    if (actt != AnchorConstraint.ANCHOR_NONE
                            && acbt != AnchorConstraint.ANCHOR_NONE) {
                        maxY = act + pref.height + acb;
                    }
                    if (actt == AnchorConstraint.ANCHOR_NONE) {
                        act = 0;
                    }
                    if (acbt == AnchorConstraint.ANCHOR_NONE) {
                        acb = 0;
                    }
                    minY = act + min.height + acb;
                }
                if (minX > minWidth) {
                    minWidth = minX;
                }
                if (maxX > minWidth) {
                    preferredWidth = maxX;
                }
                if (minY > minHeight) {
                    minHeight = minY;
                }
                if (maxY > preferredHeight) {
                    preferredHeight = maxY;
                }
            }
        }

    }

    /* (non-Javadoc)
     * @see org.eclipse.swt.widgets.Layout#layout(org.eclipse.swt.widgets.Composite, boolean)
     */
    public void layoutContainer(Container container) {
        this.container = container;
        Component children[] = container.getComponents();
        Rectangle rect = container.getBounds();
        int width = rect.width;
        int height = rect.height;
        for (int i = 0; i < children.length; i++) {
            Component child = children[i];
            if (child != null) {
                Object ld = constraintMap.get(child);
                Rectangle b = child.getBounds();
                Dimension pref = child.getPreferredSize();
                if (pref == null) {
                    pref = child.getSize();
                }
                if (ld instanceof AnchorConstraint) {
                    AnchorConstraint ac = (AnchorConstraint) ld;
                    int acl = ac.left;
                    int acr = ac.right;
                    int aclt = ac.leftType;
                    int acrt = ac.rightType;
                    if (aclt == AnchorConstraint.ANCHOR_REL) {
                        acl = acl * width / 1000;
                    }
                    if (acrt == AnchorConstraint.ANCHOR_REL) {
                        acr = width - acr * width / 1000;
                    }

                    if (aclt != AnchorConstraint.ANCHOR_NONE) {
                        if (acrt != AnchorConstraint.ANCHOR_NONE) {
                            b.width = width - acr - acl;
                            b.x = acl;
                        } else {
                            b.width = pref.width;
                            if (b.width + acl > width) {
                                b.width = width - acl;
                            }
                            b.x = acl;
                        }
                    } else {
                        if (acrt != AnchorConstraint.ANCHOR_NONE) {
                            b.x = width - acr - pref.width;
                        }
                        b.width = pref.width;
                        if (b.width + b.x > width) {
                            b.width = width - b.x;
                        }
                    }

                    int act = ac.top;
                    int acb = ac.bottom;
                    int actt = ac.topType;
                    int acbt = ac.bottomType;
                    if (actt == AnchorConstraint.ANCHOR_REL) {
                        act = act * height / 1000;
                    }
                    if (acbt == AnchorConstraint.ANCHOR_REL) {
                        acb = height - acb * height / 1000;
                    }

                    if (actt != AnchorConstraint.ANCHOR_NONE) {
                        if (acbt != AnchorConstraint.ANCHOR_NONE) {
                            b.height = height - acb - act;
                            b.y = act;
                        } else {
                            b.height = pref.height;
                            if (b.height + act > height) {
                                b.height = height - act;
                            }
                            b.y = act;
                        }
                    } else {
                        if (acbt != AnchorConstraint.ANCHOR_NONE) {
                            b.y = height - acb - pref.height;
                        }
                        b.height = pref.height;
                        if (b.height + b.y > height) {
                            b.height = height - b.y;
                        }
                    }
                    child.setBounds(b);
                }
            }
        }
    }

    /* (non-Javadoc)
     * @see java.awt.LayoutManager#addLayoutComponent(java.lang.String, java.awt.Component)
     */
    public void addLayoutComponent(String name, Component comp) {
    }

    /* (non-Javadoc)
     * @see java.awt.LayoutManager#removeLayoutComponent(java.awt.Component)
     */
    public void removeLayoutComponent(Component comp) {
        constraintMap.remove(comp);
    }

    /* (non-Javadoc)
     * @see java.awt.LayoutManager#preferredLayoutSize(java.awt.Container)
     */
    public Dimension preferredLayoutSize(Container parent) {
        initialize(parent);
        return new Dimension(preferredWidth, preferredHeight);
    }

    /* (non-Javadoc)
     * @see java.awt.LayoutManager#minimumLayoutSize(java.awt.Container)
     */
    public Dimension minimumLayoutSize(Container parent) {
        initialize(parent);
        return new Dimension(minWidth, minHeight);
    }

    /* (non-Javadoc)
     * @see java.awt.LayoutManager2#addLayoutComponent(java.awt.Component, java.lang.Object)
     */
    public void addLayoutComponent(Component comp, Object constraints) {
        constraintMap.put(comp, constraints);
    }

    /* (non-Javadoc)
     * @see java.awt.LayoutManager2#maximumLayoutSize(java.awt.Container)
     */
    public Dimension maximumLayoutSize(Container target) {
        return preferredLayoutSize(target);
    }

    /* (non-Javadoc)
     * @see java.awt.LayoutManager2#getLayoutAlignmentX(java.awt.Container)
     */
    public float getLayoutAlignmentX(Container target) {
        return 0;
    }

    /* (non-Javadoc)
     * @see java.awt.LayoutManager2#getLayoutAlignmentY(java.awt.Container)
     */
    public float getLayoutAlignmentY(Container target) {
        return 0;
    }

    /* (non-Javadoc)
     * @see java.awt.LayoutManager2#invalidateLayout(java.awt.Container)
     */
    public void invalidateLayout(Container target) {
        sizesCalculated = false;
    }
}
